package com.stormragetech.arthas.dispatcher;

import com.stormragetech.arthas.codec.ArthasHttpResponseEncodeHandler;
import com.stormragetech.arthas.common.annotation.ResponseType;
import com.stormragetech.arthas.common.constant.Constant;
import com.stormragetech.arthas.common.exception.ArthasException;
import com.stormragetech.arthas.process.context.Context;
import com.stormragetech.arthas.process.context.XmlConfigFileActionContext;
import com.stormragetech.arthas.process.factory.ActionWrapper;
import com.stormragetech.arthas.process.proxy.Proxy;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpRequest;
import lombok.extern.log4j.Log4j2;

/**
 * description: http request handler process implement
 *
 * @author: Xue Bin
 * @version: 1.0.0-SNAPSHOT
 */
@Log4j2
public class ArthasProcessHandler implements ArthasProcess {

    private static Context context;
    private String path;
    private String name;

    public void init(String name) {
        name = null == name ? "" : name;
        context = new XmlConfigFileActionContext(name);
    }

    @Override
    public FullHttpResponse process() {

        // if context is null, initialize it
        //
        if (null == context) {
            name = null == name ? "" : name;
            context = new XmlConfigFileActionContext(name);
        }

        // handle request
        //
        String result = "";
        ResponseType type = null;
        HttpRequest request = (HttpRequest) DataCache.getData();
        path = request.uri();

        try {
            // handle request
            //
            result = proxy().execute();
            type = wrapper().getResponse();
            //handle response and return
            //
            return new ArthasHttpResponseEncodeHandler(result, type).process();
        } catch (ArthasException e) {
            log.error("handle http request throw exception, cause: {}", e.toString());

            // initialize error response and return
            //
            result = Constant.ERR_MSG;
            type = ResponseType.ERROR;
            return new ArthasHttpResponseEncodeHandler(result, type).process();
        } catch (Exception e) {
            log.error("handle http request throw exception, cause: {}", e.toString());

            // initialize error response and return
            //
            result = Constant.ERR_MSG;
            type = ResponseType.ERROR;
            return new ArthasHttpResponseEncodeHandler(result, type).process();
        } finally {
            log.info("------------------------------------------------------------");
            log.info("TYPE: {}", type);
            log.info("CONTENT: {}", result.length() > 20 ? result.substring(0, 38) + "..." : result);
        }
    }

    private Proxy proxy() throws ArthasException {
        Proxy proxy = context.getProxy(wrapper());
        if (null == proxy) {
            throw new ArthasException(Constant.DISP_ERR_CODE, Constant.DISP_PROX_MSG, ArthasException.APP_ERR);
        }
        return proxy;
    }

    private ActionWrapper wrapper() throws ArthasException {

        if (null == path || path.length() <= 0) {
            throw new ArthasException(Constant.DISP_ERR_CODE, Constant.DISP_WRAP_MSG, ArthasException.APP_ERR);
        }
        ActionWrapper wrapper;
        try {
            wrapper = context.getWrapper(path);
        } catch (Exception e) {
            throw new ArthasException(Constant.DISP_ERR_CODE, Constant.DISP_WRAP_MSG, ArthasException.APP_ERR);
        }
        if (null == wrapper) {
            throw new ArthasException(Constant.DISP_ERR_CODE, Constant.DISP_WRAP_MSG, ArthasException.APP_ERR);
        }
        return wrapper;
    }

}
